package cn.sc.summer.exception.base;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.text.CharSequenceUtil;
import cn.hutool.core.util.ObjectUtil;
import org.springframework.lang.NonNull;

import java.util.Collection;
import java.util.function.Predicate;
import java.util.function.Supplier;

/**
 * 接口：断言接口方法定义
 *
 * @author a-xin
 * @date 2024/1/19 13:59
 */
public interface AssertX {

    /**
     * 创建异常的接口，具体异常可由实现类来决定
     */
    BaseException newException();

    /**
     * 创建异常的接口，具体异常可由实现类来决定，支持占位符参数列表
     */
    BaseException newException(String pattern, Object... message);

    /**
     * 断言对象是否为空
     *
     * @param bool 需要判断的对象
     */
    default void exceptionIf(@NonNull Boolean bool) {
        if (bool) {
            throw newException();
        }
    }

    /**
     * 断言对象是否为空
     *
     * @param bool    需要判断的对象
     * @param message 抛出的异常信息
     */
    default void exceptionIf(@NonNull Boolean bool, String pattern, Object... message) {
        if (bool) {
            throw newException(pattern, message);
        }
    }

    /**
     * 断言对象是否为空
     *
     * @param bool     需要判断的对象
     * @param runnable 需要执行的流程
     */
    default void exceptionIf(@NonNull Boolean bool, @NonNull Runnable runnable) {
        if (bool) {
            throw newException();
        } else {
            runnable.run();
        }
    }

    /**
     * 断言对象是否为空
     *
     * @param bool    需要判断的对象
     * @param message 抛出的异常信息
     */
    default void exceptionIf(@NonNull Boolean bool, @NonNull Runnable runnable, String pattern, Object... message) {
        if (bool) {
            throw newException(pattern, message);
        } else {
            runnable.run();
        }
    }

    /**
     * 断言对象是否为空
     *
     * @param bool     需要判断的对象
     * @param runnable 需要执行的流程
     */
    default <R> R exceptionIf(@NonNull Boolean bool, @NonNull Supplier<R> runnable) {
        if (bool) {
            throw newException();
        } else {
            return runnable.get();
        }
    }

    /**
     * 断言对象是否为空
     *
     * @param bool    需要判断的对象
     * @param message 抛出的异常信息
     */
    default <R> R exceptionIf(@NonNull Boolean bool, @NonNull Supplier<R> runnable, String pattern, Object... message) {
        if (bool) {
            throw newException(pattern, message);
        } else {
            return runnable.get();
        }
    }

    /**
     * 断言对象是否为空
     *
     * @param obj 需要判断的对象
     */
    default <T> T isNull(T obj) {
        if (ObjectUtil.isNull(obj)) {
            throw newException();
        }
        return obj;
    }

    /**
     * 断言对象是否为空
     *
     * @param obj     需要判断的对象
     * @param message 抛出的异常信息
     */
    default <T> T isNull(T obj, String pattern, Object... message) {
        if (ObjectUtil.isNull(obj)) {
            throw newException(pattern, message);
        }
        return obj;
    }

    /**
     * 断言字符串是否为空
     *
     * @param str 需要判断的字符串
     */
    default String isBlank(String str) {
        if (CharSequenceUtil.isBlank(str)) {
            throw newException();
        }
        return str;
    }

    /**
     * 断言字符串是否为空
     *
     * @param str     需要判断的字符串
     * @param message 抛出的异常信息
     */
    default String isBlank(String str, String pattern, Object... message) {
        if (CharSequenceUtil.isBlank(str)) {
            throw newException(pattern, message);
        }
        return str;
    }

    /**
     * 断言集合是否为空
     *
     * @param collection 需要判断的集合
     */
    default <T> Collection<T> isEmpty(Collection<T> collection) {
        if (CollUtil.isEmpty(collection)) {
            throw newException();
        }
        return collection;
    }

    /**
     * 断言集合是否为空
     *
     * @param collection 需要判断的集合
     * @param message    抛出的异常信息
     */
    default <T> Collection<T> isEmpty(Collection<T> collection, String pattern, Object... message) {
        if (CollUtil.isEmpty(collection)) {
            throw newException(pattern, message);
        }
        return collection;
    }

    /**
     * 根据断言判断是否抛出异常
     *
     * @param parameter 断言参数
     * @param predicate 断言方法
     * @param <P>       断言参数类型
     */
    default <P> void predicate(P parameter, @NonNull Predicate<P> predicate) {
        if (predicate.test(parameter)) {
            throw newException();
        }
    }

    /**
     * 根据断言判断是否抛出异常
     *
     * @param parameter 断言参数
     * @param predicate 断言方法
     * @param message   抛出的异常信息
     * @param <P>       断言参数类型
     */
    default <P> void predicate(P parameter, @NonNull Predicate<P> predicate, String pattern, Object... message) {
        if (predicate.test(parameter)) {
            throw newException(pattern, message);
        }
    }

    /**
     * 根据断言判断是否抛出异常
     *
     * @param parameter 断言参数
     * @param predicate 断言方法
     * @param runnable  断言后需要执行的操作，再抛出异常
     * @param <P>       断言参数类型
     */
    default <P> void predicate(P parameter, @NonNull Predicate<P> predicate, @NonNull Runnable runnable) {
        if (predicate.test(parameter)) {
            runnable.run();
            throw newException();
        }
    }

    /**
     * 根据断言判断是否抛出异常
     *
     * @param parameter 断言参数
     * @param predicate 断言方法
     * @param runnable  断言后需要执行的操作，再抛出异常
     * @param message   执行操作后抛出的异常信息
     * @param <P>       断言参数类型
     */
    default <P> void predicate(P parameter, @NonNull Predicate<P> predicate, @NonNull Runnable runnable, String pattern, Object... message) {
        if (predicate.test(parameter)) {
            runnable.run();
            throw newException(pattern, message);
        }
    }

    /**
     * 根据断言判断是否抛出异常,有返回值
     *
     * @param parameter 断言参数
     * @param predicate 断言方法
     * @param runnable  断言后需要执行的操作，再抛出异常
     * @param <P>       断言参数类型
     */
    default <P, R> R predicate(P parameter, @NonNull Predicate<P> predicate, @NonNull Supplier<R> runnable) {
        if (predicate.test(parameter)) {
            return runnable.get();
        } else {
            throw newException();
        }
    }

    /**
     * 根据断言判断是否抛出异常,有返回值
     *
     * @param parameter 断言参数
     * @param predicate 断言方法
     * @param runnable  断言后需要执行的操作，再抛出异常
     * @param <P>       断言参数类型
     */
    default <P, R> R predicate(P parameter, @NonNull Predicate<P> predicate, @NonNull Supplier<R> runnable, String pattern, Object... message) {
        if (predicate.test(parameter)) {
            return runnable.get();
        } else {
            throw newException(pattern, message);
        }
    }

}

